package bachelor.view {
	import CustomEvent.CustomEvent;

	import bachelor.Globals;
	import bachelor.datamanagement.XMLLoader;

	import fiducialTuioAS3.tuio.TouchEvent;

	import gs.TweenLite;
	import gs.TweenMax;
	import gs.easing.Cubic;

	import flash.display.MovieClip;
	import flash.events.Event;

	/** ABLAUF
	 * ======================================================
	 *         Constructor
	 *             
	 *             
	 *       keywordActivated   
	 *             
	 *            
	 *        loadImagePath  > > > >>>>>>>> XMLLoader
	 *                                   
	 *                                   
	 *      onXMLLoadedHander<<<<<<<<<<<<<<<<< Event
	 *      

	 *        initAllLayer >>>>>>>>>>>>>>>>  Layer >>>>>>>>>>>>>>>>>>>> Pic
	 *                                                  
	 *                                                  
	 * onLastLayerLoadedHandler <<<<<<<<<<<<< Layer  <<<<<<<<<<<<<<<<Event
	 *           

	 *       GUI > initInterface
	 *       GUI > initScala 
	 *		  moveLayers
	 * ======================================================
	 */
	public class CountryPanel extends MovieClip  
	{


////////////////////////////////////////////////////////////////////////////////
/////// VARIABLES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
		private var _id : int;
		private var _xml : XML;
		
		// Layoutarrangement
		private var _xOffset : int = -95;
		private var _yOffset : int = -85;
		private var _startRotation : int;
		private var _tintColor : uint;
		private var _tintColorIndex : int;
		private var _activeGrid : int = 4;
	
		private var _activatedKeywordID : int;

		private var _myXMLLoader 	: XMLLoader;
		private var _loadingState	: Boolean = false;
		

		private var _layerArray	: Array = new Array();
		private var _loadedLayerCounter : int = 0;
		private var _lastLayerIndex : int = 0;
		private var _currentLayerIndex : int = 0;

		private var _interface 	: MovieClip = new MovieClip();
		private var _rotateButton  : MovieClip = new MovieClip();

		private var _gridButton1  : GridButton;
		private var _gridButton4  : GridButton;
		private var _gridButton16 : GridButton;

		// Events
		public static const LAYERS_ADDED : String = "layersAdded";
		public static const COUNTRY_PANEL_DEINITIALIZED : String = "countryPanelDeinitialized";
		public static const GRID_CHANGED : String = "gridChanged";

		// TEMP
		public static const CREATE_BOOKMARK : String = "createBookmark";


////////////////////////////////////////////////////////////////////////////////
/////// CONSTRUCTOR ////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////		
		public function CountryPanel(p_id : int, p_startRotation : Number, p_tintColorIndex : int, p_activeKeywordID : int) 
		{			
//			trace("CountryPanel -> Constructor init... fuer Country no " + p_id);
			
			_activatedKeywordID = p_activeKeywordID;
			
			_id = p_id;
			/*
			 * Die Start-Rotation muss bei der Scala-Rotation miteinberechnet werden
			 */
			_startRotation = Math.round(p_startRotation);
//			trace("CountryPanel -> Constructor ... _startRotation: " + _startRotation);
			if(_startRotation < 0) 
			{
				_startRotation += 360;
//				trace("CountryPanel -> Constructor ... _startRotation war < 0, NEUER Werte: " + _startRotation);
			}
			/*
			 * Farbe-Index im Array fuer onRemove zwischenspeichern
			 */
			_tintColorIndex = p_tintColorIndex;
			_tintColor = Globals.countryColorArray[p_tintColorIndex][1];
			
			/*
			 * Land wird erst erstellt, wenn Keyword schon gelegt ist.
			 * Deshalb sofort die XML laden und anschliessend die Layers und Pics.
			 */
			loadImagePaths(_activatedKeywordID);
			initPanel();
		}
		


////////////////////////////////////////////////////////////////////////////////
/////// METHODS ////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/////// INIT Panel /////////////////////////////////////////////////////////
		private function initPanel() : void
		{
//			trace("CountryPanel -> initPanel() ...");
	
			var _panel : MovieClip = MovieClip(new countryPanelMC());
			_panel.x = 0;
			_panel.y = 0;
			_interface.addChild(_panel);

			///// BUTTONS //////
			_rotateButton.x = -220;
			_rotateButton.y = -190;
			addChild(_rotateButton);


			// Erstelle die 3 Buttons je mit BitMaps und Methoden fuer seine eigene grafische Darstellung
 			_gridButton1 = new GridButton(1); 
			_gridButton1.x = -185 - _xOffset;
			_gridButton1.y = 22 - _yOffset;
			_gridButton1.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
			_interface.addChild(_gridButton1);

 			_gridButton4 = new GridButton(4);
			_gridButton4.x = -149 - _xOffset;
			_gridButton4.y = 22 - _yOffset;
			_gridButton4.activate();
			//_gridButton4.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);  // Mit Grid 4 wird gestartet
			_interface.addChild(_gridButton4);

 			_gridButton16 = new GridButton(16);
			_gridButton16.x = -113 - _xOffset;
			_gridButton16.y = 22 - _yOffset;
			_gridButton16.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
			_interface.addChild(_gridButton16);
			
			_interface.x = _xOffset;
			_interface.y = _yOffset;
			_interface.alpha = 0;
			addChild(_interface);
			_interface.visible = true;
		}

		
		
		////////////////////////////////////////////////////////////////////////////////
/////// KEYWORD ACTIVATED / DEACTIVATED ////////////////////////////////////////


/////// Keyword aktiviert //////////////////////////////////////////////////////
//		public function keywordActivated(p_activeKeywordID : int) : void 
//		{
//			trace("CountryPanel -> keywordActivated() ...");
//			loadImagePaths(p_activeKeywordID);
//		}


/////// Land ausblenden, dann loschen //////////////////////////////////////////
		public function deinitializeCountry() : void 
		{
//			trace("CountryPanel -> deinitializeCountry() ...");
			removeAllLayers();
			hidePanel();
		}

		
////////////////////////////////////////////////////////////////////////////////
/////// XML LADEVORGANG ////////////////////////////////////////////////////////


/////// XML laden ////////////////////////////////////////////////////////
		private function loadImagePaths(p_activeKeywordID : int) : void
		{
//			trace("CountryPanel -> loadImages() ...");
			var XMLPath : String = "bin/pics/" + Globals.keywordArray[p_activeKeywordID][0] + "/country" + Globals.countryArray[_id][1] + "/data" + Globals.countryArray[_id][1] + ".xml";			
			_myXMLLoader = new XMLLoader(XMLPath, this);
			_myXMLLoader.addEventListener(XMLLoader.XML_LOADED, onXMLLoadedHandler);
			
		}

/////// XML fertig /////////////////////////////////////////////////////////////
		private function onXMLLoadedHandler(evt : CustomEvent) : void
		{
//			trace("CountryPanel -> onXMLLoaderHandler() ...");
			var myCompletedXMLLoader : XMLLoader = evt.target as XMLLoader;
			myCompletedXMLLoader.removeEventListener(XMLLoader.XML_LOADED, onXMLLoadedHandler);
			_xml = evt.data as XML;
			initAllLayers();
		}

////////////////////////////////////////////////////////////////////////////////
/////// INITs //////////////////////////////////////////////////////////////////


/////// INIT All-Layers /////////////////////////////////////////
		public function initAllLayers() : void
		{
//			trace("CountryPanel -> initAllLayers() init...");
			/*
			 * Falls das Country während des Ladens schon wieder entfernt wird, 
			 * muss das Entfernen durch die GUI anders passieren.
			 */
			_loadingState = true;
			/*
			 * Erstellt entsprechend des aktuellen Grids 
			 * die benoetige Anzahl der Layers inkl. der Pics 
			 * innerhalb des SlideshowMCs
			 */
			for(var i:int = 0; i < (48/_activeGrid); i++) 
			{
//				trace("Country -> initAllLayers() ::: erstelle Layer " + _layerArray.length);
				
				var newLayer : Layer = newLayer = new Layer(_xml, i, _activeGrid);
				/*
				 * Layer perspektivisch sehr weit hinten erstellen
				 */
				newLayer.z = i * 10;
				newLayer.x = _xOffset-1; 
				newLayer.y = _yOffset - 18;
				newLayer.alpha = 0;

				newLayer.addEventListener(Layer.CREATE_BOOKMARK, createBookmarkHandler);
				newLayer.addEventListener(Layer.SINGLE_LAYER_LODED, onSingleLayerLoadedHandler);
				/*
				 * Layer vorne im Layer-Array einfuegen
				 */ 
				_layerArray[i] = newLayer;
				addChildAt(newLayer, 0);
				/*
				 * Schon mal den zIndex neu sortieren, damit das _interface an Position 2 steht
				 * Das Einblenden der Layers kommt erst nach dem Laden der Bitmaps
				 */
				
			}
			changeDepths(0);
			
		}
		
/////// DEINIT All-Layers //////////////////////////////////////////////////////
		private function removeAllLayers() : void 
		{
//			trace("CountryPanel -> hideAllLayers() ...");
			
			/*
			 * Alle Layers von der Buehne entfernen
			 */
			for(var i:int = 0; i < _layerArray.length; i++)
			{
				var layerToRemove : Layer = _layerArray[i] as Layer;
				/*
				 * Layer darf bei fertigem Laden, nicht mehr mitgezählt werden.
				 */
				TweenLite.to(layerToRemove, 1, {alpha: 0, ease: Cubic.easeOut, onComplete: removeLayer, onCompleteParams: [layerToRemove]});
			}
			/*
			 * Inhalte loschen wegen Performance
			 */
			_layerArray = [];
			_loadedLayerCounter = 0;
		}
		
		private function removeLayer(p_layerObj : Layer) : void 
		{
//			trace("CountryPanel -> removeLayer() für " + p_layerObj);
			p_layerObj.removeEventListener(Layer.SINGLE_LAYER_LODED, onSingleLayerLoadedHandler);
			removeChild(p_layerObj);
		}

		
/////// Bilder fertig geladen, jetzt Elemente einblenden ///////////////////////
		private function onSingleLayerLoadedHandler(evt : Event) : void 
		{
			var singleLoadedLayer : Layer = evt.target as Layer;
			singleLoadedLayer.removeEventListener(Layer.SINGLE_LAYER_LODED, onSingleLayerLoadedHandler);

			/*
			 * Bei jeder geladenen Layer, mitzählen
			 */
			_loadedLayerCounter++;
//			trace("CountryPanel -> onSingleLayerLoadedHandler() ... " + _loadedLayerCounter);
			
			/*
			 * Wenn alle Layer geladen sind, darf es grafisch weitergehen
			 */
			if(_loadedLayerCounter >= (48 / _activeGrid))
			{
				/*
				 * Lade-Status wieder auf false setzen, 
				 * ist beim Entfernen des Landes wichtig
				 */
				_loadingState = false;
				/*
				 * Panel einblenden
				 */
				showPanel();
				/*
				 * Scala einblenden
				 */
				dispatchEvent(new Event(LAYERS_ADDED));
				/*
				 * Layers erstmalig hereinfahren und erste Ebene (0) klickbar machen 
				 */ 
				moveLayers(_currentLayerIndex, "vor");
			}			
		}

		


/////// HIDE PANEL ///////////////////////////////////////////////////////
		private function hidePanel() : void 
		{
//			trace("CountryPanel -> hidePanel() ...");
			TweenLite.to(_interface, Globals.fadeTime, {alpha: 0, ease:Cubic.easeOut, onComplete: onCountryDeinitialized});
		}
/////// SHOW PANEL ///////////////////////////////////////////////////////
		private function showPanel() : void 
		{
//			trace("CountryPanel -> hidePanel() ...");
			_interface.visible = true;
			TweenLite.to(_interface, Globals.fadeTime, {alpha: 1, ease:Cubic.easeIn});
		}
		
/////// Country fertig ausgeblendet ////////////////////////////////////////////
		private function onCountryDeinitialized() : void 
		{
//			trace("CountryPanel -> onCountryDeinitialized() ...");
			dispatchEvent(new Event(COUNTRY_PANEL_DEINITIALIZED));
			removeChild(_interface);
		}





////////////////////////////////////////////////////////////////////////////////
/////// MOVE LAYERS ////////////////////////////////////////////////////////////
		public function moveLayers(p_newLayerIndex : int, p_direction : String) : void 
		{						// p_newLayerIndex = Index des aktuell oben angezeigten Layers
		
//			trace("Country -> moveLayers() ::: p_currentLayerIndex = " + p_newLayerIndex);
			_currentLayerIndex = p_newLayerIndex;
			/*
			 *  Abfragen, ob schon alle Layers erstellt sind
			 */
			
			if(_layerArray.length >= (48 / _activeGrid)) 
			{


				
				for(var i:int = 0; i < _layerArray.length; i++) 
				{	/*
					 * Clickbare Ebene = newLayerIndex
					 */
					
					var newAlpha : Number = get3DAlpha(i-p_newLayerIndex);
					// Differenz der Array-Position zum neuen LayerIndex + "Rückstand" vom letzten Tween bei schnellen Drehen
					var zDiff : Number = (i-p_newLayerIndex) * 10 - _layerArray[i].z;
					
					
					
					if(p_direction == "vor") 
					{ // VOR
							
							if(i == p_newLayerIndex) {
								// Bewegen, mit Tiefen-Tausch im Anschluss
								manageLayerVisible(i, p_newLayerIndex);
								_layerArray[i].makeClickable();
								TweenMax.to(_layerArray[i], Globals.fadeTime, {z: (_layerArray[i].z + zDiff), alpha: newAlpha, overwrite:2,  ease: Cubic.easeOut, onComplete: changeDepths, onCompleteParams: [i]});
						} else if(i == (p_newLayerIndex-1)) 
							{
								// Bewegen, ohne Tiefen-Tausch, mit visible=false im Anschluss
								_layerArray[i].makeUnclickable();
								TweenLite.to(_layerArray[i], (Globals.fadeTime/4), {z: (_layerArray[i].z + zDiff), alpha: newAlpha, overwrite:2,  ease: Cubic.easeOut, onComplete: manageLayerVisible, onCompleteParams: [i, p_newLayerIndex]});
							} else 
							{
								// Bewegen, ohne Tiefen-Tausch
								manageLayerVisible(i, p_newLayerIndex);
								_layerArray[i].makeUnclickable(); //RAUS?
								TweenLite.to(_layerArray[i], Globals.fadeTime, {z: (_layerArray[i].z + zDiff), alpha: newAlpha, overwrite:2,  ease: Cubic.easeOut});
							}
					
					} else 
					{ // ZURÜCK
								
							if(i == p_newLayerIndex) {
								// Bewegen, mit Tiefen-Tausch im Anschluss
								manageLayerVisible(i, p_newLayerIndex);
								_layerArray[i].makeClickable();
								TweenLite.to(_layerArray[i], Globals.fadeTime, {z: (_layerArray[i].z + zDiff), alpha: newAlpha, overwrite:2,  ease: Cubic.easeOut, onComplete: changeDepths, onCompleteParams: [i]});
								
							} else if(i == (p_newLayerIndex+1)) 
							{
								// Bewegen, ohne Tiefen-Tausch, mit visible=false im Anschluss
								_layerArray[i].makeUnclickable();
								TweenLite.to(_layerArray[i], Globals.fadeTime, {z: (_layerArray[i].z + zDiff), alpha: newAlpha, overwrite:2,  ease: Cubic.easeOut, onComplete: manageLayerVisible, onCompleteParams: [i, p_newLayerIndex]});
								
							} else 
							{
								// Bewegen, ohne Tiefen-Tausch
								manageLayerVisible(i, p_newLayerIndex);
								_layerArray[i].makeUnclickable();
								TweenLite.to(_layerArray[i], Globals.fadeTime, {z: (_layerArray[i].z + zDiff), alpha: newAlpha, overwrite:2,  ease: Cubic.easeOut});
							}
											
					}
					

				}

				 //Letzten Layerstep zwischenspeicern
				_lastLayerIndex = p_newLayerIndex;

			}
		}
		
		private function manageLayerVisible(p_i : int, p_newLayerIndex : int) : void 
		{
			if(p_i < (p_newLayerIndex-1)) 
			{
				// Alle "oberen" ausblenden
				_layerArray[p_i].visible = false;
				
			} else if(p_i == (p_newLayerIndex-1)) {
				// Die Ebene, die sich ausblenden soll
				_layerArray[p_i].visible = false;
				
			} else if(p_i < (p_newLayerIndex + Globals.layerDepth)) {
				// Clickbare und die ersten 4 "hinteren" Ebenen sind sichtbar
				_layerArray[p_i].visible = true;
				
			} else {
				// Ab der 5. "hinteren" Ebenen sind alle unsichtbar
				_layerArray[p_i].visible = false;
			}
		}

		
		
		private function changeDepths(p_i : int) : void 
		{
//			trace("Country -> changeDepths() ::: Richtung: " + p_direction + " - Layer " + p_i + " ist fertig getweent auf z=" + _layerArray[p_i].z);
//			if(p_direction == "vor")
//			{
				
				if(getChildIndex(_layerArray[p_i]) < getChildIndex(_interface))
				{
					// Layer HINTER _interface
					setChildIndex(_interface, getChildIndex(_layerArray[p_i]));
				} else 
				{
					// Layer VOR _interface
					setChildIndex(_interface, (getChildIndex(_layerArray[p_i])-1));
				}

//			} else 
//			{
//				if(getChildIndex(_layerArray[p_i]) < getChildIndex(_interface))
//				{
//					// Layer HINTER _interface
//					setChildIndex(_interface, getChildIndex(_layerArray[p_i]));
//				} else 
//				{
//					// Layer VOR _interface
//					setChildIndex(_interface, (getChildIndex(_layerArray[p_i])-1));
//				}
//			}


			
		}

		
		
////////////////////////////////////////////////////////////////////////////////
/////// BUTTONS ////////////////////////////////////////////////////////////////

/////// Grid-Button gedruckt ///////////////////////////////////////////////////
		private function gridButtonPressedHandler(evt : TouchEvent) : void 
		{
//			trace("CountryPanel -> gridButtonPressedHandler() ...");
			switch(evt.currentTarget) 
			{
				case _gridButton1:
//					trace("Jetzt wird ins Grid 1 gewechselt");
					// EventListeners neu organisieren
					_gridButton1.removeEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
					_gridButton1.activate();
					if(_activeGrid == 4) {
						_gridButton4.deactivate();
						_gridButton4.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
					} else if(_activeGrid == 16)
					{
						_gridButton16.deactivate();
						_gridButton16.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
					}
					// Alle Layers ausblenden
					removeAllLayers();
					// activeGrid neu definieren und Scala anpassen 
					_activeGrid = 1;
					dispatchEvent(new CustomEvent(GRID_CHANGED, [_id, _activeGrid]));
					// Layers neu einladen
					initAllLayers();
					break;
					
				case _gridButton4:
//					trace("Jetzt wird ins Grid 4 gewechselt");
					// EventListeners neu organisieren
					_gridButton4.removeEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
					_gridButton4.activate();
					if(_activeGrid == 1) 
					{
						_gridButton1.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
						_gridButton1.deactivate();
					} else if(_activeGrid == 16)
					{
						_gridButton16.deactivate();
						_gridButton16.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
					}
					// Alle Layers ausblenden
					removeAllLayers();
					// activeGrid neu definieren und Scala anpassen 
					_activeGrid = 4;
					dispatchEvent(new CustomEvent(GRID_CHANGED, [_id, _activeGrid]));
					// Layers neu einladen
					initAllLayers();
					break;
					
				case _gridButton16:
//					trace("Jetzt wird ins Grid 16 gewechselt");
					// EventListeners neu organisieren
					_gridButton16.removeEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
					_gridButton16.activate();
					if(_activeGrid == 1) 
					{
						_gridButton1.deactivate();
						_gridButton1.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
					} else if(_activeGrid == 4)
					{
						_gridButton4.deactivate();
						_gridButton4.addEventListener(TouchEvent.MOUSE_DOWN, gridButtonPressedHandler);
					}
					// Alle Layers ausblenden
					removeAllLayers();
					// activeGrid neu definieren und Scala anpassen 
					_activeGrid = 16;
					dispatchEvent(new CustomEvent(GRID_CHANGED, [_id, _activeGrid]));
					// Layers neu einladen
					initAllLayers();
					break;
			}
		}

/*			
// 		private function btnPressed(e:Event) : void 
//		{
//			// e.target = _myBtn1 ODER _myBtn2 ODER _myBtn3
//			entsperreAlleButtons();
// 			e.target.makeMeUntouchable();
//			removeAllLayers();
// 			_activeGrid = e.target.id;
//			initAllLayers(//param);
//		}
//
//		private function entsperreAlleButton() :void {
//			_myBtn1.makeMeTouchable();
//			_myBtn2.makeMeTouchable();
//			_myBtn3.makeMeTouchable();
//		}
//
//		private Function removeAllLayers() {
//			// Leere das Array layerArray
//		}
*/





//////////////////////////////////////////////////////////////////////////////////
///////// BOOKMARKS //////////////////////////////////////////////////////////////


		private function createBookmarkHandler(evt : CustomEvent) : void 
		{
//			trace("CountryPanel -> createBookmarkHandler() ... dispatchingEvent...");
			var dataArray : Array = evt.data as Array;
			dataArray.push(_tintColor);
			dataArray.push(_id);
			dispatchEvent(new CustomEvent(CREATE_BOOKMARK, dataArray));
		}







		
		
////////////////////////////////////////////////////////////////////////////////
/////// HELPERS ////////////////////////////////////////////////////////////////


/////// 3D-Berechnungen ////////////////////////////////////////////////////////
		private function get3DAlpha(p_3D_ID : int) : Number 
		{
//			trace("CountryPanel -> get3DLook() ...");
			/**
			 *  Diese Funktion errechnet folgendes: 
			 *  p_3D_ID < 0  >>>  Unsichtbare, groesse Ebene
			 *  p_3D_ID = 0  >>>  Sichtbare, oberste Ebene
			 *  p_3D_ID > 0  >>>  Sichtbare, hintere Ebene
			 */
			var new3DFactor : Number = 1 / Math.sqrt(Math.sqrt( (p_3D_ID + 1) ));
			new3DFactor = Math.floor(new3DFactor * 100) / 100; 
			
			var returnVar : Number;
			if(p_3D_ID >= 0) 
			{
				returnVar = Math.pow(new3DFactor, 8);
			} else 
			{
				// Ausblenden, weil in die Tiefe gescrollt
				returnVar = 0.05;
			}
			return returnVar;
		}
		
		

		
		


////////////////////////////////////////////////////////////////////////////////
/////// GETTERS & SETTERS //////////////////////////////////////////////////////


/////// TintColor-Index fur onRemove zuruckgeben ///////////////////////////////
		public function getTintColorIndex() : int 
		{
			return _tintColorIndex;
		}


/////// ID zuruckgeben /////////////////////////////////////////////////////////
		public function getID() : int 
		{
			return _id;
		}

/////// Ladestatus beim Entfernen zuruckgeben //////////////////////////////////
		public function getLoadingState() : Boolean 
		{
			return _loadingState;
		}













////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
	}
}
